﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using EF_Model;
using Moq;
using System;
using System.Data.Objects;
using System.Linq;

namespace EF_Tests
{
    [TestClass]
    public class Repository_Call_Verify_Test
    {
        // Add Methods

        [TestMethod]
        public void Customer_Repository_Class_AddCustomer_Method_Should_Call_ObjectSet_AddObject_Method()
        {
            Mock<IObjectSet<Customer>> customers = new Mock<IObjectSet<Customer>>();
            customers.Setup(cust => cust.AddObject(It.IsAny<Customer>())).Verifiable();

            Mock<DatabaseContext> db = new Mock<DatabaseContext>();
            db.Setup(_db => _db.Customers).Returns(customers.Object);

            CustomerRepository customerRepository = new CustomerRepository(db.Object);

            customerRepository.AddCustomer(new Customer());

            customers.Verify();//passes

        }

        //[TestMethod] < NO TESTABLE>
        //public void Customer_Repository_Class_AddToCustomer_Method_Should_Call_ObjectContext_AddToCustomer_Method()
        //{
        //    Mock<IObjectSet<Customer>> customers = new Mock<IObjectSet<Customer>>();
            
        //    Mock<DatabaseContext> db = new Mock<DatabaseContext>();
        //    db.Setup(_db => _db.Customers).Returns(customers.Object);
        //    db.Setup(_db => _db.AddToCustomers(It.IsAny<Customer>())).Verifiable();

        //    CustomerRepository customerRepository = new CustomerRepository(db.Object);

        //    customerRepository.AddToCustomer(new Customer());

        //    db.Verify();//fails, since _db.AddToCustomers is non-overridable

        //}

        // Delete Methods

        [TestMethod]
        public void Customer_Repository_Class_DeleteCustomer_Method_Should_Call_ObjectSet_DeleteObject_Method()
        {
            Mock<IObjectSet<Customer>> customers = new Mock<IObjectSet<Customer>>();
            customers.Setup(cust => cust.DeleteObject(It.IsAny<Customer>())).Verifiable();

            Mock<DatabaseContext> db = new Mock<DatabaseContext>();
            db.Setup(_db => _db.Customers).Returns(customers.Object);

            CustomerRepository customerRepository = new CustomerRepository(db.Object);

            customerRepository.DeleteCustomer(new Customer());

            customers.Verify();//passes

        }

        //[TestMethod] < NO TESTABLE>
        //public void Customer_Repository_Class_DeleteFromCustomers_Method_Should_Call_ObjectContext_DeleteObject_Method()
        //{
        //    //Mock<IObjectSet<Customer>> customers = new Mock<IObjectSet<Customer>>();

        //    Mock<DatabaseContext> db = new Mock<DatabaseContext>();
        //    //db.Setup(_db => _db.Customers).Returns(customers.Object);
        //    db.Setup(_db => _db.DeleteObjectFromContext(It.IsAny<Customer>())).Verifiable();

        //    CustomerRepository customerRepository = new CustomerRepository(db.Object);

        //    customerRepository.DeleteFromCustomers(new Customer());

        //    db.Verify();//fails, since _db.DeleteObject is non-overridable

        //}

        //Save Methods

        [TestMethod]
        public void Customer_Repository_Class_SaveLatestChanges_Method_Should_Call_ObjectContext_SaveChanges_Method()
        {
            Mock<DatabaseContext> db = new Mock<DatabaseContext>();
            db.Setup(_db => _db.SaveChanges()).Verifiable();

            //to make the SaveChanges method veriable we have created a virtual method 
            //SaveChanges that calls base.SaveChanges. However in this case we need another verifyable method for DbContext.SaveLatestChanges ??

            UnitOfWork unitOfWork = new UnitOfWork(db.Object);
            unitOfWork.Commit();

            db.Verify();//passes, since default _db.SaveChanges is non-overridable, we had to create a proxy method

        }

        // Read Methods ????

        [TestMethod]
        public void Customer_Repository_Class_GetById_Method_Should_Call_FirstOrDefault_Method()
        {
            Mock<IObjectSet<Customer>> customers = new Mock<IObjectSet<Customer>>();
            //customers.Setup(cust => cust.FirstOrDefault(It.IsAny<IQueryable>)).Verifiable();

            Mock<DatabaseContext> db = new Mock<DatabaseContext>();
            db.Setup(_db => _db.Customers).Returns(customers.Object);

            CustomerRepository customerRepository = new CustomerRepository(db.Object);

            customerRepository.AddCustomer(new Customer());

            customers.Verify();//fails

        }
    }
}
